package com.easyJava.builder;

import com.easyJava.bean.ClassType;
import com.easyJava.bean.Constants;
import com.easyJava.bean.FieldInfo;
import com.easyJava.bean.TableInfo;
import com.easyJava.utils.DateUtils;
import com.sun.xml.internal.ws.api.server.SDDocument;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.Buffer;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 *  1. 有一个小问题，就是在生成po文件的时候，如果有is_xxx , 并且是Boolean 类型 , set get 方法会有问题
 * 这是一个用来生成po文件的类
 */
public class BuildMapper {

    private static final Logger logger = LoggerFactory.getLogger(BuildMapper.class);

    public static final String EXTENDS = " extends ";

    //T是方法参数  P是结果
    public static final String GENERICS = "<T,P>";

    public static final String BASEMAPPER ="BaseMapper";


    public static final String BEAN = "bean";

    public static final String PARAM = "@Param";

    public static final String UPDATE = "update";
    public static final String DELETE = "delete";
    public static final String SELECT = "select";

    public static final String BY = "By";

    public static final String AND = "And";

    public static final String T = "T";

    public static final String t = "t";


    public static final String PARAM_CLASS="import org.apache.ibatis.annotations.Param;";


    public static final String UPDATE_WORK = "更新";

    public static final String SELECT_WORK = "查询";

    public static final String DELETE_WORK = "删除";

    /**
     * 生成po文件
     * @param tableInfo
     */
    public static void execute(TableInfo tableInfo){
        File folder = new File(Constants.PATH_MAPPER);
        if(!folder.exists()){
            folder.mkdirs();
        }
        File file_mapper = new File(folder,tableInfo.getBeanName() + Constants.MAPPER_NAME+".java");
        OutputStream outputStream =null;
        OutputStreamWriter outputStreamWriter = null;
        BufferedWriter bufferedWriter = null;

        try{
            outputStream = new FileOutputStream(file_mapper);
            outputStreamWriter = new OutputStreamWriter(outputStream,"utf-8");
            bufferedWriter = new BufferedWriter(outputStreamWriter);
            //包名
            bufferedWriter.write("package " + Constants.PACKAGE_MAPPER + ";" );
            bufferedWriter.newLine();

            Map<String, List<FieldInfo>> keyIndexMap = tableInfo.getKeyIndexMap();
            //导入Param
            if(keyIndexMap!= null || keyIndexMap.size() > 0){
                bufferedWriter.write(PARAM_CLASS);
                bufferedWriter.newLine();
            }
            BuildComment.ClassComment(bufferedWriter,tableInfo);
            bufferedWriter.newLine();
            bufferedWriter.write("public interface " + tableInfo.getBeanName()  + Constants.MAPPER_NAME + GENERICS+ EXTENDS+ BASEMAPPER +GENERICS + "{");
            bufferedWriter.newLine();
            bufferedWriter.newLine();
            //处理字段

            for(Map.Entry<String,List<FieldInfo>>entry:keyIndexMap.entrySet()){
                String key = entry.getKey();
                List<FieldInfo> fieldInfoList = entry.getValue();
                updateKey(bufferedWriter,fieldInfoList,key);
                DeleteKey(bufferedWriter,fieldInfoList,key);
                SelectKey(bufferedWriter,fieldInfoList,key);
            }

            bufferedWriter.write("}");
            bufferedWriter.flush();
        }catch (Exception e){
            logger.error("生成mapper文件失败",e);
        }finally {
            try {
                bufferedWriter.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                outputStreamWriter.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                outputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
    /**
     * 主键的更新接口
     * @param bs
     * @param fieldInfoList
     */
    public static void updateKey(BufferedWriter bs ,List<FieldInfo> fieldInfoList,String key) throws IOException {

        if(fieldInfoList.size() == 0 || fieldInfoList == null){
            return;
        }
        StringBuffer bf = new StringBuffer();
        bf.append("\t" + ClassType.INTERGER + " " + UPDATE+BY);
        StringBuffer Parameter = new StringBuffer();
        //参数
        Parameter.append("(" +PARAM + "(\"" + BEAN + "\")" + T + " " + t + ",");
        String CollectionName = new String();
        for(int i = 0 ;i<fieldInfoList.size();i++){
          String propertyName = fieldInfoList.get(i).getPropertyName().substring(0,1).toUpperCase() + fieldInfoList.get(i).getPropertyName().substring(1);
          if(i != fieldInfoList.size()- 1){
                propertyName += AND;
                Parameter.append(PARAM + "(\"" + fieldInfoList.get(i).getPropertyName() + "\")" + fieldInfoList.get(i).getJavaType() + " " + fieldInfoList.get(i).getPropertyName() + ",");
            }else {
                Parameter.append(PARAM + "(\"" + fieldInfoList.get(i).getPropertyName() + "\")" + fieldInfoList.get(i).getJavaType() + " " + fieldInfoList.get(i).getPropertyName());
            }
            CollectionName += propertyName;
            bf.append(propertyName);
        }
        BuildComment.mapperMethodComment(UPDATE_WORK,CollectionName,bs);
        bs.write(bf.toString() + Parameter.toString() + ");");
        bs.newLine();
        bs.newLine();
    }


    /**
     * 主键的接口
     * @param bs
     * @param fieldInfoList
     */
    public static void DeleteKey(BufferedWriter bs ,List<FieldInfo> fieldInfoList,String key) throws IOException {

        if(fieldInfoList.size() == 0 || fieldInfoList == null){
            return;
        }
        StringBuffer bf = new StringBuffer();
        bf.append("\t" + ClassType.INTERGER + " " + DELETE+BY);
        StringBuffer Parameter = new StringBuffer();
        //参数
        Parameter.append("(" +PARAM + "(\"" + BEAN + "\")" + T + " " + t + ",");
        String CollectionName = new String();
        for(int i = 0 ;i<fieldInfoList.size();i++){
            String propertyName = fieldInfoList.get(i).getPropertyName().substring(0,1).toUpperCase() + fieldInfoList.get(i).getPropertyName().substring(1);
            if(i != fieldInfoList.size()- 1){
                propertyName += AND;
                Parameter.append(PARAM + "(\"" + fieldInfoList.get(i).getPropertyName() + "\")" + fieldInfoList.get(i).getJavaType() + " " + fieldInfoList.get(i).getPropertyName() + ",");
            }else {
                Parameter.append(PARAM + "(\"" + fieldInfoList.get(i).getPropertyName() + "\")" + fieldInfoList.get(i).getJavaType() + " " + fieldInfoList.get(i).getPropertyName());
            }
            CollectionName += propertyName;
            bf.append(propertyName);
        }
        BuildComment.mapperMethodComment(DELETE_WORK,CollectionName,bs);
        bs.write(bf.toString() + Parameter.toString() + ");");
        bs.newLine();
        bs.newLine();
    }

    /**
     * 主键查询接口
     * @param bw
     * @param fieldInfoList
     */
    public static void SelectKey(BufferedWriter bw ,List<FieldInfo> fieldInfoList,String key) throws IOException {
        if(fieldInfoList.size() == 0 || fieldInfoList == null){
            return;
        }
        StringBuffer bf = new StringBuffer();
        bf.append("\t" + T + " " + SELECT +BY);
        StringBuffer Parameter = new StringBuffer();
        //参数
        Parameter.append("(" );
        String CollectionName = new String();
        for(int i = 0 ;i<fieldInfoList.size();i++){
            String propertyName = fieldInfoList.get(i).getPropertyName().substring(0,1).toUpperCase() + fieldInfoList.get(i).getPropertyName().substring(1);
            if(i != fieldInfoList.size()- 1){
                propertyName += AND;
                Parameter.append(PARAM + "(\"" + fieldInfoList.get(i).getPropertyName() + "\")" + fieldInfoList.get(i).getJavaType() + " " + fieldInfoList.get(i).getPropertyName() + ",");
            }else {
                Parameter.append(PARAM + "(\"" + fieldInfoList.get(i).getPropertyName() + "\")" + fieldInfoList.get(i).getJavaType() + " " + fieldInfoList.get(i).getPropertyName());
            }
            CollectionName += propertyName;
            bf.append(propertyName);
        }
        BuildComment.mapperMethodComment(SELECT_WORK,CollectionName,bw);
        bw.write(bf.toString() + Parameter.toString() + ");");
        bw.newLine();
        bw.newLine();
    }
}
